#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <stdbool.h>

#include <libcc_stl/xml_parser.h>
#include <libcc_stl/list.h>
#include <libcc_stl/math.h>
#include <libcc_net/ip.h>

#include "xml_tree_parser.h"

#include "configure_read.h"

struct ddos_conf global_ddos_conf;

#define XML_VALUE_CHECK_OK      1
#define XML_VALUE_CHECK_FALSE   0

static int check_integer(const char* s, void* args)
{
    int i;
    for(i = 0; i < strlen(s); ++i)
    {
        if(s[i] >= '0' && s[i] <= '9')
        {
            continue;
        }
        return XML_VALUE_CHECK_FALSE;
    }

    return XML_VALUE_CHECK_OK;
}

static inline int check_hex_c(const char s, void* args)
{
    if(
        (s >= '0' && s <= '9') ||
        (s >= 'a' && s <= 'f') ||
        (s >= 'A' && s <= 'F')
    )
    {
        return XML_VALUE_CHECK_OK;
    }
    return XML_VALUE_CHECK_FALSE;
}


static int check_integer_0_1(const char* s, void* args)
{
    int i;
    if(1 == strlen(s) && ('0' == s[0] || '1' == s[0]))
    {
        return XML_VALUE_CHECK_OK;
    }

    return XML_VALUE_CHECK_FALSE;
}

static int check_mac_address(const char* s, void* args)
{
    int split_count = 0;
    int i = 0;
    int j = 0;
    int k = 0;

    printf("Check mac: %s\r\n", s);
    while(i < strlen(s) && (i + 1) < strlen(s))
    {
        if(XML_VALUE_CHECK_OK == check_hex_c(s[i], 0) &&  XML_VALUE_CHECK_OK == check_hex_c(s[i + 1], 0))
        {
            if((i + 2) < strlen(s))
            {
                if(s[i + 2] == ':')
                {
                    i += 3;
                    j++;
                    continue;
                }
            }
            else
            {
                break;
            }

        }

    }

    if(j == 5)
    {
        return XML_VALUE_CHECK_OK;
    }

label_error_mac_address:
    fprintf(stderr, "%s - mac address %s is invalid\n", __func__, s);
    return XML_VALUE_CHECK_FALSE;
}


static int check_ipv4_address(const char* str, void* args)
{
    int segs = 0;   /* Segment count. */
    int chcnt = 0;  /* Character count within segment. */
    int accum = 0;  /* Accumulator for segment. */

    /* Catch NULL pointer. */

    if(str == NULL)
    {
        return XML_VALUE_CHECK_FALSE;
    }

    /* Process every character in string. */

    while(*str != '\0')
    {
        /* Segment changeover. */

        if(*str == '.')
        {
            /* Must have some digits in segment. */

            if(chcnt == 0)
            {
                return XML_VALUE_CHECK_FALSE;
            }

            /* Limit number of segments. */

            if(++segs == 4)
            {
                return XML_VALUE_CHECK_FALSE;
            }

            /* Reset segment values and restart loop. */

            chcnt = accum = 0;
            str++;
            continue;
        }



        /* Check numeric. */

        if((*str < '0') || (*str > '9'))
        {
            return XML_VALUE_CHECK_FALSE;
        }

        /* Accumulate and check segment. */

        if((accum = accum * 10 + *str - '0') > 255)
        {
            return XML_VALUE_CHECK_FALSE;
        }

        /* Advance other segment specific stuff and continue loop. */

        chcnt++;
        str++;
    }

    /* Check enough segments and enough characters in last segment. */

    if(segs != 3)
    {
        return XML_VALUE_CHECK_FALSE;
    }

    if(chcnt == 0)
    {
        return XML_VALUE_CHECK_FALSE;
    }

    /* Address okay. */

    return XML_VALUE_CHECK_OK;
}


static int check_ipv4_netmask(const char* str, void* args)
{
    int i;
    for(i = 0; i < strlen(str); ++i)
    {
        if(str[0] >= '0' && str[0] <= '9')
        {
            continue;
        }
        return XML_VALUE_CHECK_FALSE;
    }

    i = atoi(str);
    if(i <= 0 || i > 32)
    {
        return XML_VALUE_CHECK_FALSE;
    }

    return XML_VALUE_CHECK_OK;
}

static int check_port(const char* s, void* args)
{
    if(XML_VALUE_CHECK_OK == check_integer(s, 0))
    {
        if(atoi(s) >= 0 && atoi(s) < 65536)
        {
            return XML_VALUE_CHECK_OK;
        }
    }

    return XML_VALUE_CHECK_FALSE;
}

static int check_payload_content_in_hex(const char* s, void* args)
{
    int i = 0;

    while(i < strlen(s))
    {
        // printf("%d\n", i);
        if(isspace(s[i]))
        {
            i++;
            continue;
        }

        if(i < strlen(s) && (i + 1) < strlen(s))
        {
            if(XML_VALUE_CHECK_OK == check_hex_c(s[i], 0) && XML_VALUE_CHECK_OK == check_hex_c(s[i + 1], 0))
            {
                if((i + 2) == strlen(s))
                {
                    return XML_VALUE_CHECK_OK;
                }

                if(isspace(s[i + 2]))
                {
                    // printf("%c %c %c %d;\n", s[i], s[i + 1], s[i + 2], i);
                    i += 2;
                    continue;
                }
                else
                {
                    return XML_VALUE_CHECK_FALSE;
                }

            }
            else
            {
                return XML_VALUE_CHECK_FALSE;
            }
        }
        else
        {
            return XML_VALUE_CHECK_FALSE;
        }
    }

    return XML_VALUE_CHECK_OK;
}


static inline void init_pps(const char* s, const char* node_name, const char* attrib_name, struct ddos_conf* f)
{
    f->control.pps = atoi(s);
    f->control.usleep_count = (f->control.pps) ? (1000000 / f->control.pps) : 0;
    fprintf(stdout, "%-20s %-20s %-5s %d\n", node_name, attrib_name, "", f->control.pps);
}

static inline void init_interface(const char* s, const char* node_name, const char* attrib_name, struct ddos_conf* f)
{
    strcpy(f->control.interface, s);
    fprintf(stdout, "%-20s %-20s %-5s %s\n", node_name, attrib_name, "", f->control.interface);
}

static inline void init_total_count(const char* s, const char* node_name, const char* attrib_name, struct ddos_conf* f)
{
    f->control.total_count = atoi(s);
    fprintf(stdout, "%-20s %-20s %-5s %d\n", node_name, attrib_name, "", f->control.total_count);
}

static inline void init_sampling(const char* s, const char* node_name, const char* attrib_name, struct ddos_conf* f)
{
    if(0 == strcmp("capture", attrib_name))
    {
        strcpy(f->control.pcap_file, s);
        fprintf(stdout, "%-20s %-20s %-5s %s\n", node_name, attrib_name, "", f->control.pcap_file);
    }

    /*
    else if(0 == strcmp("sampling_rate", attrib_name))
    {
        // f->control.sampling_rate = ALIGN2TWO(atoi(s));
        // fprintf(stdout, "%-20s %-20s %-5s %d\n", node_name, attrib_name, "", f->control.sampling_rate);
    }
    */
}


static inline void init_source_mac(const char* s, const char* node_name, const char* attrib_name, struct ddos_conf* f)
{
    int i = sscanf(s, "%x:%x:%x:%x:%x:%x",
                   f->eth_h.source + 0,
                   f->eth_h.source + 1,
                   f->eth_h.source + 2,
                   f->eth_h.source + 3,
                   f->eth_h.source + 4,
                   f->eth_h.source + 5
                  );

    fprintf(stdout, "%-20s %-20s %-5s %hhx:%hhx:%hhx:%hhx:%hhx:%hhx\n",
            node_name,
            attrib_name,
            "",
            f->eth_h.source[0],
            f->eth_h.source[1],
            f->eth_h.source[2],
            f->eth_h.source[3],
            f->eth_h.source[4],
            f->eth_h.source[5]
           );


}

static inline void init_ip_source_addr(const char* s, const char* node_name, const char* attrib_name, struct ddos_conf* f)
{
    // f->control.total_count = atoi(s);
    // fprintf(stdout, "%-20s %-20s %10d\n", node_name, attrib_name, f->control.total_count);
    char addr[4] = {0};
    sscanf(s, "%d.%d.%d.%d",
           addr + 0,
           addr + 1,
           addr + 2,
           addr + 3
          );

    IPv4_ADDR_SET(f->ip_h.saddr, addr[0], addr[1], addr[2], addr[3]);
    fprintf(stdout, "%-20s %-20s %-5s %d.%d.%d.%d\n", node_name, attrib_name, "", NIPQUAD(f->ip_h.saddr));

}

static inline void init_ip_dest_addr(const char* s, const char* node_name, const char* attrib_name, struct ddos_conf* f)
{
    // f->control.total_count = atoi(s);
    // fprintf(stdout, "%-20s %-20s %10d\n", node_name, attrib_name, f->control.total_count);
    char addr[4] = {0};
    sscanf(s, "%d.%d.%d.%d",
           addr + 0,
           addr + 1,
           addr + 2,
           addr + 3
          );

    IPv4_ADDR_SET(f->ip_h.daddr, addr[0], addr[1], addr[2], addr[3]);
    fprintf(stdout, "%-20s %-20s %-5s %d.%d.%d.%d\n", node_name, attrib_name, "", NIPQUAD(f->ip_h.daddr));
}



static inline void init_dest_mac(const char* s, const char* node_name, const char* attrib_name, struct ddos_conf* f)
{
    int i = sscanf(s, "%x:%x:%x:%x:%x:%x",
                   f->eth_h.dest + 0,
                   f->eth_h.dest + 1,
                   f->eth_h.dest + 2,
                   f->eth_h.dest + 3,
                   f->eth_h.dest + 4,
                   f->eth_h.dest + 5
                  );

    fprintf(stdout, "%-20s %-20s %-5s %hhx:%hhx:%hhx:%hhx:%hhx:%hhx\n",
            node_name,
            attrib_name,
            "",
            f->eth_h.dest[0],
            f->eth_h.dest[1],
            f->eth_h.dest[2],
            f->eth_h.dest[3],
            f->eth_h.dest[4],
            f->eth_h.dest[5]
           );
}


static inline void init_ip_source_netmask(const char* s, const char* node_name, const char* attrib_name, struct ddos_conf* f)
{
    f->source_netmask = atoi(s);
    if(subnet_info_init(&f->source_subnet, f->ip_h.saddr, f->source_netmask))
    {
        fprintf(stdout, "%-20s %-20s %-5s %d %d.%d.%d.%d ~ %d.%d.%d.%d\n", node_name, attrib_name, "", f->source_netmask,
                NIPQUAD(f->source_subnet.start),
                NIPQUAD(f->source_subnet.end)
               );
    }
}

static inline void init_ip_dest_netmask(const char* s, const char* node_name, const char* attrib_name, struct ddos_conf* f)
{
    f->dest_netmask = atoi(s);
    if(subnet_info_init(&f->dest_subnet, f->ip_h.daddr, f->dest_netmask))
    {
        fprintf(stdout, "%-20s %-20s %-5s %d %d.%d.%d.%d ~ %d.%d.%d.%d\n", node_name, attrib_name, "", f->dest_netmask,
                NIPQUAD(f->dest_subnet.start),
                NIPQUAD(f->dest_subnet.end)
               );
    }

}


static inline void init_tcp_port(const char* s, const char* node_name, const char* attrib_name, struct ddos_conf* f)
{

    if(0 == strcmp(attrib_name, "source"))
    {
        f->tcp_h.source = htons(atoi(s));
        fprintf(stdout, "%-20s %-20s %-5s %d\n", node_name, attrib_name, "", ntohs(f->tcp_h.source));
    }
    else
    {
        f->tcp_h.dest = htons(atoi(s));
        fprintf(stdout, "%-20s %-20s %-5s %d\n", node_name, attrib_name, "", ntohs(f->tcp_h.dest));
    }

}

static inline void init_udp_port(const char* s, const char* node_name, const char* attrib_name, struct ddos_conf* f)
{

    if(0 == strcmp(attrib_name, "source"))
    {
        f->udp_h.source = htons(atoi(s));
        fprintf(stdout, "%-20s %-20s %-5s %d\n", node_name, attrib_name, "", ntohs(f->udp_h.source));
    }
    else
    {
        f->udp_h.dest = htons(atoi(s));
        fprintf(stdout, "%-20s %-20s %-5s %d\n", node_name, attrib_name, "", ntohs(f->udp_h.dest));
    }

}


static inline void init_tcp_falgs(const char* s, const char* node_name, const char* attrib_name, struct ddos_conf* f)
{
    if(0 == strcmp(attrib_name, "flag_crw"))
    {
        f->tcp_h.cwr = atoi(s);
    }
    else if(0 == strcmp(attrib_name, "flag_ece"))
    {
        f->tcp_h.ece = atoi(s);
    }
    else if(0 == strcmp(attrib_name, "flag_urg"))
    {
        f->tcp_h.urg = atoi(s);
    }
    else if(0 == strcmp(attrib_name, "flag_ack"))
    {
        f->tcp_h.ack = atoi(s);
    }
    else if(0 == strcmp(attrib_name, "flag_psh"))
    {
        f->tcp_h.psh = atoi(s);
    }
    else if(0 == strcmp(attrib_name, "flag_rst"))
    {
        f->tcp_h.rst = atoi(s);
    }
    else if(0 == strcmp(attrib_name, "flag_syn"))
    {
        f->tcp_h.syn = atoi(s);
    }
    else if(0 == strcmp(attrib_name, "flag_fin"))
    {
        f->tcp_h.fin = atoi(s);
    }

    fprintf(stdout, "%-20s %-20s %-5s %d\n", node_name, attrib_name, "", atoi(s));
}

static inline void init_tcp_seq_num(const char* s, const char* node_name, const char* attrib_name, struct ddos_conf* f)
{
    f->tcp_h.seq = htonl(atoi(s));

    fprintf(stdout, "%-20s %-20s %-5s %d \r\n", node_name, attrib_name, "", ntohl(f->tcp_h.seq));
}

static inline void init_payload(const char* s, const char* node_name, const char* attrib_name, struct ddos_conf* f)
{
    static int pyalod_len_init = 0;
    int payload_content_len = 0;
    int i = 0;

    if(0 == strcmp(attrib_name, "len"))
    {
        f->payload.payload_len = atoi(s);
        pyalod_len_init = 1;
        fprintf(stdout, "%-20s %-20s %-5s %d\r\n", node_name, attrib_name, "", f->payload.payload_len);
    }
    else if(0 == strcmp(attrib_name, "content"))
    {
        if(pyalod_len_init && 0 == f->payload.payload_len)
        {
            return;
        }

        while(i < strlen(s))
        {
            if(isspace(s[i]))
            {
                i++;
                continue;
            }

            if(i < strlen(s) && (i + 1) < strlen(s))
            {
                // printf(">> %s\r\n", s + i);
                sscanf(s + i, "%x",  f->payload.payload + (payload_content_len++));
                i += 2;
            }
        }

        if(!pyalod_len_init)
        {
            f->payload.payload_len = payload_content_len;
        }

        fprintf(stdout, "%-20s %-20s %-5s", node_name, attrib_name, "");
        for(i = 0; i < f->payload.payload_len; ++i)
        {
            fprintf(stdout, "%02hhx ", f->payload.payload[i]);
        }
        fprintf(stdout, "\r\n");

    }
}

static inline void init_http_header(const char* s, const char* node_name, const char* attrib_name, struct ddos_conf* f)
{
    // strcpy(f->http_header, s);
    // printf("!!!!!!!!! %s", s);
    int j = 0;
    int i = 0;
    char last = 0;
    for(i = 0; i < strlen(s); ++i)
    {

        if(s[i] == '\r' && s[i + 1] != '\n')
        {
            f->http_header[j++] = '\r';
            f->http_header[j++] = '\n';
        }
        else if (last != '\r' && s[i] == '\n')
        {
            f->http_header[j++] = '\r';
            f->http_header[j++] = '\n';
        }
        else
        {
            f->http_header[j++] = s[i];
        }

        last = s[i];
    }

    fprintf(stdout, "%-20s %-20s %-5s %s \r\n", node_name, attrib_name, "", f->http_header);
}

static inline void init_dns(const char* s, const char* node_name, const char* attrib_name, struct ddos_conf* f)
{
    if(0 == strcmp(attrib_name, "id"))
    {
        f->dns_h.id = htons(atoi(s));
        fprintf(stdout, "%-20s %-20s %-5s %d \r\n", node_name, attrib_name, "", atoi(s));
    }
    else if(0 == strcmp(attrib_name, "rd_flag"))
    {
        f->dns_h.flags = 0;
        if(atoi(s))
        {
            f->dns_h.flags = htons(DNS_FLAG_RD);
        }
        else
        {
            // f->dns_h.flags = htons(DNS_FLAG_QR);
        }
        fprintf(stdout, "%-20s %-20s %-5s %x \r\n", node_name, attrib_name, "", f->dns_h.flags);
    }
    else if(0 == strcmp(attrib_name, "query"))
    {
        char* p1 = (char*)s;
        char* p2 = (char*)s;
        char* p3 = 0;
        int len = 0;
        int j = 0;

        f->query_domain[0] = '.';
        strcpy(f->query_domain + 1, s);
        p3 = f->query_domain + strlen(f->query_domain) - 1;
        p1 = f->query_domain;

        for(p2 = p3; p2 >= p1; --p2)
        {
            if(p2[0] == '.')
            {
                p2[0] = len;
                len = 0;
                continue;
            }
            len++;
        }

        fprintf(stdout, "%-20s %-20s %-5s \r\n", node_name, attrib_name, "");
        for(j = 0; j <= strlen(f->query_domain); ++j)
        {
            fprintf(stdout, "%d ", f->query_domain[j]);
        }
        fprintf(stdout, "\r\n");
    }
}



// Root
struct xml_parser_tree_node* ddos_root = 0;

// Layer1
struct xml_parser_tree_node* eth_xp_root = 0;

// Layer2
struct xml_parser_tree_node* ip_xp_root = 0;

// Layer3
struct xml_parser_tree_node* tcp_xp_root = 0;
struct xml_parser_tree_node* udp_xp_root = 0;

// Layer4
struct xml_parser_tree_node* tcp_http_xp_root = 0;
struct xml_parser_tree_node* udp_dns_xp_root = 0;

struct xml_parser_tree_node* payload_xp_root = 0;


static inline void init_xml_parser_tree(int type)
{
    struct xml_parser_tree_node* payload_parent = 0;

    ddos_root = push_xp_node(NULL, "ddos", DDOS_TYPE_BASE, 0);
    assert(ddos_root);
    assert(push_xp_attrib(ddos_root, "pps", check_integer, (value_init_fp)init_pps));
    assert(push_xp_attrib(ddos_root, "interface", 0, (value_init_fp)init_interface));
    assert(push_xp_attrib(ddos_root, "total_count", 0, (value_init_fp)init_total_count));
    // assert(push_xp_attrib(ddos_root, "capture", 0, (value_init_fp)(init_sampling));
    // assert(push_xp_attrib(ddos_root, "sampling", 0, (value_init_fp)init_sampling));
    // assert(push_xp_attrib(ddos_root, "sampling_rate", check_integer, (value_init_fp)init_sampling));
    // assert(push_xp_attrib(ddos_root, "type", 0, init_ddos_type));

    eth_xp_root = push_xp_node(ddos_root, "ethernate", DDOS_TYPE_ETHNATE, 0);
    assert(eth_xp_root);
    assert(push_xp_attrib(eth_xp_root, "source", check_mac_address, (value_init_fp)init_source_mac));
    assert(push_xp_attrib(eth_xp_root, "dest", check_mac_address, (value_init_fp)init_dest_mac));

    ip_xp_root = push_xp_node(eth_xp_root, "ip", DDOS_TYPE_IP, 0);
    assert(ip_xp_root);
    assert(push_xp_attrib(ip_xp_root, "source", check_ipv4_address, (value_init_fp)init_ip_source_addr));
    assert(push_xp_attrib(ip_xp_root, "dest", check_ipv4_address, (value_init_fp)init_ip_dest_addr));
    assert(push_xp_attrib(ip_xp_root, "source_netmask", check_ipv4_netmask, (value_init_fp)init_ip_source_netmask));
    assert(push_xp_attrib(ip_xp_root, "dest_netmask", check_ipv4_netmask, (value_init_fp)init_ip_dest_netmask));

    udp_xp_root = push_xp_node(ip_xp_root, "udp", DDOS_TYPE_IP_UDP, 0);
    assert(udp_xp_root);
    assert(push_xp_attrib(udp_xp_root, "source", check_port, (value_init_fp)init_udp_port));
    assert(push_xp_attrib(udp_xp_root, "dest", check_port, (value_init_fp)init_udp_port));

    udp_dns_xp_root = push_xp_node(udp_xp_root, "dns", DDOS_TYPE_IP_UDP_DNS, 0);
    assert(udp_dns_xp_root);
    assert(push_xp_attrib(udp_dns_xp_root, "id", check_integer, (value_init_fp)init_dns));
    assert(push_xp_attrib(udp_dns_xp_root, "rd_flag", check_integer, (value_init_fp)init_dns));
    assert(push_xp_attrib(udp_dns_xp_root, "query", 0, (value_init_fp)init_dns));

    tcp_xp_root = push_xp_node(ip_xp_root, "tcp", DDOS_TYPE_IP_TCP, 0);
    assert(tcp_xp_root);
    assert(push_xp_attrib(tcp_xp_root, "source", check_port, (value_init_fp)init_tcp_port));
    assert(push_xp_attrib(tcp_xp_root, "dest", check_port, (value_init_fp)init_tcp_port));
    assert(push_xp_attrib(tcp_xp_root, "flag_crw", check_integer_0_1, (value_init_fp)init_tcp_falgs));
    assert(push_xp_attrib(tcp_xp_root, "flag_ece", check_integer_0_1, (value_init_fp)init_tcp_falgs));
    assert(push_xp_attrib(tcp_xp_root, "flag_urg", check_integer_0_1, (value_init_fp)init_tcp_falgs));
    assert(push_xp_attrib(tcp_xp_root, "flag_ack", check_integer_0_1, (value_init_fp)init_tcp_falgs));
    assert(push_xp_attrib(tcp_xp_root, "flag_psh", check_integer_0_1, (value_init_fp)init_tcp_falgs));
    assert(push_xp_attrib(tcp_xp_root, "flag_rst", check_integer_0_1, (value_init_fp)init_tcp_falgs));
    assert(push_xp_attrib(tcp_xp_root, "flag_syn", check_integer_0_1, (value_init_fp)init_tcp_falgs));
    assert(push_xp_attrib(tcp_xp_root, "flag_fin", check_integer_0_1, (value_init_fp)init_tcp_falgs));
    assert(push_xp_attrib(tcp_xp_root, "seq_num", check_integer, (value_init_fp)init_tcp_seq_num));

    tcp_http_xp_root = push_xp_node(tcp_xp_root, "http", DDOS_TYPE_IP_TCP_HTTP, 0);
    assert(tcp_http_xp_root);
    assert(push_xp_attrib(tcp_http_xp_root, "head", 0, (value_init_fp)init_http_header));

    if(type == DDOS_TYPE_IP_UDP)
    {
        payload_parent = udp_xp_root;
    }
    if(type == DDOS_TYPE_IP_TCP)
    {
        payload_parent = tcp_xp_root;
    }

    if(payload_parent)
    {
        payload_xp_root = push_xp_node(payload_parent, "payload", payload_parent->type, 0);
        assert(payload_xp_root);
        assert(push_xp_attrib(payload_xp_root, "len", check_integer, (value_init_fp)init_payload));
        assert(push_xp_attrib(payload_xp_root, "content", check_integer, (value_init_fp)init_payload));
    }
}


static inline int _parse_xml_doc(const struct xml_node* node, struct xml_parser_tree_node* parser, int type)
{
    struct xml_parser_tree_node* cur_node_parser = 0;
    struct xml_parser_tree_leaf* cur_attrib_parser = 0;
    const struct xml_node* cur_xml_node = 0;
    struct list_head* it;
    const char* value = 0;

    // memset(&global_ddos_conf, 0, sizeof(global_ddos_conf));

    assert(0 == strcmp(xml_node_name(node), parser->name));


    // printf("\r\n  Parse For Node %s attribs:\r\n", parser->name);
    list_for_each(it, &parser->attribs)
    {
        cur_attrib_parser = (struct xml_parser_tree_leaf*)it;

        value = xml_node_attrib_value((const struct xml_node*)node, cur_attrib_parser->name);
        // printf("> %s:%s\r\n", cur_attrib_parser->name, value);

        if(!value || (cur_attrib_parser->check_fp && XML_VALUE_CHECK_FALSE == cur_attrib_parser->check_fp(value, 0)))
        {
            fprintf(stderr, "%s - Check value for %s failed!\r\n", __func__, cur_attrib_parser->name);
            return false;
        }

        cur_attrib_parser->init_fp(value, xml_node_name(node), cur_attrib_parser->name, &global_ddos_conf);
    }


    // printf("\r\nParse For Node %s child nodes:\r\n", parser->name);
    list_for_each(it, &parser->children)
    {
        cur_node_parser = (struct xml_parser_tree_node*)it;

        // ONLY prarse essential childs
        if((cur_node_parser->type & type) == cur_node_parser->type)
        {
            // printf("## %s\r\n", cur_node_parser->name);
            cur_xml_node = xml_node_child_search((const struct xml_node*)node, cur_node_parser->name);
            // printf("## == ?  %s\r\n", xml_node_name(cur_xml_node));

            if(!cur_xml_node)
            {
                fprintf(stderr, "%s - Node <%s /> need child <%s> <%s/>\r\n", __func__, xml_node_name(node), cur_node_parser->name, cur_node_parser->name);

                xml_node_child_print(node);

                return false;
            }

            if(_parse_xml_doc(cur_xml_node, cur_node_parser, type))
            {
                continue;
            }
            return false;
        }
    }

    return true;
}

int parse_configuration_xml(const char* type_name, const char* file)
{
    struct xml_doc* doc = 0;
    struct xml_node* root = 0;
    int type = get_type_from_name(type_name);
    int ret = false;

    global_ddos_conf.type = type;

    printf("Open XML file %s for %s\r\n", file, type_name);
    doc = xml_doc_open(file);


    if(0 == doc)
    {
        fprintf(stderr, "Cannot open file %s for read!\n", file);
        ret = false;
        // return false;
        goto label_parse_failed;
    }

    printf("Parse XML file %s for %s\r\n", file, type_name);
    root = xml_doc_parse(doc);
    if(0 == root)
    {
        fprintf(stderr, "Parse Xml file %s failed!\r\n", file);
        ret = false;
        goto label_parse_failed;
    }

    init_xml_parser_tree(type);

    if(_parse_xml_doc(root, ddos_root, type))
    {
        ret = true;
        fprintf(stdout, "Parse finised!");
    }
    else
    {
        ret = false;
        fprintf(stderr, "Parse failed!!!!!");
    }


label_parse_failed:

    if(ddos_root)
    {
        pop_xp_node(ddos_root);
    }

    if(root)
    {
        xml_node_free(root);
    }

    if(doc)
    {
        xml_doc_close(doc);
    }

    printf("\r\n!!!!! ######################### !!!!!!!!!!\r\n\r\n");
    return ret;

}

